Skip to content

Conversation

@oveddan
Copy link
Collaborator

@oveddan oveddan commented Sep 18, 2025

Summary

FIXED: Resolves critical hook migration bug that caused CannotUpdateEmptyPosition() errors when migrating from hooks that store two positions in the same ticks.

Bug Description

Location: V4Liquidity.burnPositions() function
Error: CannotUpdateEmptyPosition()
Cause: Function attempted to modify positions with liquidityDelta: 0 on already-empty positions

Root Cause Analysis

The migration logic tried to burn positions that had zero liquidity, causing Uniswap V4's position validation to reject the operation:

// In Position.sol - the validation that was failing:
if (liquidityDelta == 0) {
    if (liquidity == 0) CannotUpdateEmptyPosition.selector.revertWith(); // ← This error
}

This can happen when we initial a hook for a coin, and our initial liquidity position calculations result in adding liquidity twice to a position with the same ticks.

This behavior can be seen in the uniswap Position.t.sol test:

    function test_fuzz_update(
        int128 liquidityDelta,
        Position.State memory pos,
        uint256 newFeeGrowthInside0X128,
        uint256 newFeeGrowthInside1X128
    ) public {
        Position.State storage position = positions[0];
        position.liquidity = pos.liquidity;
        position.feeGrowthInside0LastX128 = pos.feeGrowthInside0LastX128;
        position.feeGrowthInside1LastX128 = pos.feeGrowthInside1LastX128;

        uint128 oldLiquidity = position.liquidity;

        if (position.liquidity == 0 && liquidityDelta == 0) {
            vm.expectRevert(Position.CannotUpdateEmptyPosition.selector);
        }
}

Fix Applied

Added empty position check in V4Liquidity.sol line ~201-210:

// Skip positions that have no liquidity to avoid CannotUpdateEmptyPosition error  
if (liquidity == 0) {
    burnedPositions[i] = BurnedPosition({
        tickLower: positions[i].tickLower,
        tickUpper: positions[i].tickUpper, 
        amount0Received: 0,
        amount1Received: 0
    });
    continue; // Skip the modifyLiquidity call
}

Impact Resolved

  • Hook version 1.1.2 migrations now work for both content and creator coins
  • Production coins can upgrade from problematic hook versions
  • No more blocked upgrade paths for existing users
  • Backward compatibility maintained for all valid positions

🤖 Generated with Claude Code

@oveddan oveddan force-pushed the fix-liquidity-migration-bug branch from fc02dc9 to 33a8966 Compare September 18, 2025 18:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants